﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
using LiteDB;

namespace Jinndev.DB {

    /// <summary>
    /// 封装数据库接口
    /// </summary>
    public class DatabaseInstance {

        public LiteDatabase Database { get; private set; }

        public bool Ready { get { return Database != null; } }

        public DatabaseInstance(string connectionString) {
            Database = new LiteDatabase(connectionString);
        }

        public DatabaseInstance(Stream stream) {
            Database = new LiteDatabase(stream);
        }

        public void Dispose() {
            Database?.Dispose();
            Database = null;
        }

        public bool Commit() {
            return Database == null ? false : Database.Commit();
        }

        public bool CollectionExists(string name) {
            return Database == null ? false : Database.CollectionExists(name);
        }

        public bool RenameCollection(string oldName, string newName) {
            return Database == null ? false : Database.RenameCollection(oldName, newName);
        }

        public bool DropCollection(string name) {
            return Database == null ? false : Database.DropCollection(name);
        }

        public bool Rollback() {
            return Database == null ? false : Database.Rollback();
        }


        public bool Insert<T>(T entity) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Insert(entity) != null;
        }

        public int Insert<T>(IEnumerable<T> entities) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Insert(entities);
        }

        public bool Update<T>(T entity) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Update(entity);
        }

        public bool Upsert<T>(T entity) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Upsert(entity);
        }

        public T FindOne<T>(Expression<Func<T, bool>> predicate) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.FindOne(predicate);
        }

        public T FindById<T>(object id) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.FindById(new BsonValue(id));
        }

        public bool Delete<T>(object id) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Delete(new BsonValue(id));
        }

        public int DeleteAll<T>() {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.DeleteAll();
        }

        public int DeleteMany<T>(Expression<Func<T, bool>> predicate) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.DeleteMany(predicate);
        }

        public IEnumerable<T> Find<T>(Expression<Func<T, bool>> predicate, int skip = 0, int limit = int.MaxValue) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Find(predicate, skip, limit);
        }

        public IEnumerable<T> FindAll<T>() {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.FindAll();
        }

        public bool Exists<T>(Expression<Func<T, bool>> predicate) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Exists(predicate);
        }

        public ILiteCollection<T> Include<T, K>(Expression<Func<T, K>> keySelector) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Include(keySelector);
        }

        public int Count<T>() {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Count();
        }

        public int Count<T>(Expression<Func<T, bool>> predicate) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Count(predicate);
        }

        public long LongCount<T>() {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.LongCount();

        }
        public long LongCount<T>(Expression<Func<T, bool>> predicate) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.LongCount(predicate);
        }

        public K Max<T, K>(Expression<Func<T, K>> keySelector) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Max(keySelector);
        }

        public K Min<T, K>(Expression<Func<T, K>> keySelector) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.Min(keySelector);
        }

        public bool EnsureIndex<T, K>(Expression<Func<T, K>> keySelector, bool unique = false) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.EnsureIndex(keySelector, unique);
        }

        public bool EnsureIndex<T, K>(string name, Expression<Func<T, K>> keySelector, bool unique = false) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.EnsureIndex(name, keySelector, unique);
        }

        public bool DropIndex<T>(string name) {
            ILiteCollection<T> collection = Database.GetCollection<T>();
            return collection.DropIndex(name);
        }

    }

}